package com.yhsoft.benefitcard.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yhsoft.benefitcard.controller.request.AddCardsBatch1InVo;
import com.yhsoft.benefitcard.controller.request.SetFlimBatchAddPriceInVo;
import com.yhsoft.benefitcard.controller.response.*;
import com.yhsoft.benefitcard.entity.BatchGoods;
import com.yhsoft.benefitcard.entity.CardsBatch2;
import com.yhsoft.benefitcard.entity.CardsInfo;
import com.yhsoft.benefitcard.mapper.CardsBatch2Mapper;
import com.yhsoft.benefitcard.mapper.CardsInfoMapper;
import com.yhsoft.benefitcard.service.ICardsInfoService;
import com.yhsoft.buyer.entity.BuyerOrder;
import com.yhsoft.buyer.entity.OrderCard;
import com.yhsoft.buyer.mapper.BuyerOrderMapper;
import com.yhsoft.buyer.service.IOrderCardService;
import com.yhsoft.common.service.TokenService;
import com.yhsoft.common.utils.IDGenerator;
import com.yhsoft.flim.controller.response.DYOrderOutVo;
import com.yhsoft.goods.mapper.GoodsInfoMapper;
import com.yhsoft.mall.entity.TopicInfo;
import com.yhsoft.mall.mapper.TopicInfoMapper;
import com.yhsoft.sys.entity.BaicContent;
import com.yhsoft.sys.entity.CustomerInfo;
import com.yhsoft.sys.mapper.CustomerInfoMapper;
import com.yhsoft.sys.service.IBaicContentService;
import com.yhsoft.wxprogram.controller.response.BenefitCardOutVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 福利卡信息表 服务实现类
 * </p>
 *
 * @author yyyyyyyh
 * @since 2023-10-04
 */
@Service
public class CardsInfoServiceImpl extends ServiceImpl<CardsInfoMapper, CardsInfo> implements ICardsInfoService {

    @Resource
    private CardsBatch2Mapper batch2Mapper;

    @Resource
    private CustomerInfoMapper customerInfoMapper;

    @Resource
    private GoodsInfoMapper goodsInfoMapper;

    @Resource
    private IOrderCardService iOrderCardService;

    @Resource
    private BuyerOrderMapper buyerOrderMapper;

    @Resource
    private IBaicContentService iBaicContentService;

    @Resource
    private TopicInfoMapper topicInfoMapper;

    @Override
    public void addCardsInfo(AddCardsBatch1InVo inVo, String batchNum) {
        for (int a = 1; a <= inVo.getCardSize(); a++) {
            CardsInfo cardsInfo = new CardsInfo();
            cardsInfo.setFirstBatchNum(batchNum);
            cardsInfo.setCardType(inVo.getCardType());
            // 账号密码待完善
            StringBuilder cardsNum = new StringBuilder();
            cardsNum.append(batchNum).append(IDGenerator.padNumber(a));
            cardsInfo.setBenefitCardsNum(cardsNum.toString());
            cardsInfo.setBenefitCardsPassword(IDGenerator.getUUIDByUUId());
            cardsInfo.setIsActivated(0);
            baseMapper.insert(cardsInfo);
        }
    }

    @Override
    public String bindingCard(String cardNum, String cardPassword) {
        String msg = "绑定成功！";
        LambdaQueryWrapper<CardsInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CardsInfo::getBenefitCardsNum, cardNum);
        CardsInfo cardsInfo = baseMapper.selectOne(wrapper);
        if (cardsInfo == null) {
            msg = "卡号输入错误！请重新输入。";
            return msg;
        }
        if (StringUtils.hasLength(cardsInfo.getUserId())) {
            msg = "您所输入的福利卡已被绑定，请重新输入卡号。";
            return msg;
        }
        if (!cardsInfo.getBenefitCardsPassword().equals(cardPassword)) {
            msg = "无法匹配福利卡，请重新输入。";
            return msg;
        }
        QueryWrapper<CardsBatch2> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("second_bantch_num", cardsInfo.getSecondBantchNum());
        CardsBatch2 cardsBatch2 = batch2Mapper.selectOne(queryWrapper);
        // 判断批次是否激活
        if (cardsBatch2 == null) {
            msg = "您所输入的福利卡未激活！请激活后使用。";
            return msg;
        }
        // 有时间限制，并且当前时间比结束时间晚,提示过期
        if (cardsBatch2.getIsLimitedDate() == 1 && LocalDate.now().isAfter(cardsBatch2.getEndTime())) {
            msg = "您所输入的福利卡已过期，请重新输入卡号。";
            return msg;
        }
        // 判断批次是否冻结 1-正常，0-冻结
        if (cardsBatch2.getIsEnable() == 0) {
            msg = "您所输入的福利卡已被冻结！请解冻后使用。";
            return msg;
        }
        // 绑定
        cardsInfo.setUserId(TokenService.getUserBytoken().getId());
        baseMapper.updateById(cardsInfo);
        return msg;
    }

    @Override
    public List<BenefitCardOutVo> getBenefitCard() {
        QueryWrapper<BenefitCardOutVo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", TokenService.getUserBytoken().getId());
        // 过滤已使用的电影券，积分卡
        wrapper.eq("a.is_used", 0);
        List<BenefitCardOutVo> list = this.baseMapper.selectBenefitCardOutVoList(wrapper);
        BaicContent baicContent = iBaicContentService.getThisBaicContent();
        if (list.size() > 0) {
            list.forEach(a -> {
                a.setWxappCurrency(baicContent.getWxappCurrency());
                a.setCurrencyIcon(baicContent.getCurrencyIcon());
                if (StringUtils.hasLength(a.getSalesTopicId())) {
                    TopicInfo topicInfo = topicInfoMapper.selectById(a.getSalesTopicId());
                    a.setSalesTopicName(topicInfo.getName());
                }
            });
            return list;
        }

        return null;
    }

    @Override
    public void setCardInUse(Integer cardId) {
        LambdaQueryWrapper<CardsInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CardsInfo::getUserId, TokenService.getUserBytoken().getId());
        List<CardsInfo> cardsInfos = this.baseMapper.selectList(queryWrapper);
        cardsInfos.forEach(a -> {
            if (a.getId().equals(cardId)) {
                a.setIsInUse(1);
                this.baseMapper.updateById(a);
            } else {
                a.setIsInUse(0);
                this.baseMapper.updateById(a);
            }
        });
    }

    @Override
    public BenefitCardOutVo getInUseCard() {
        QueryWrapper<BenefitCardOutVo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", TokenService.getUserBytoken().getId());
        wrapper.eq("is_in_use", 1);
        List<BenefitCardOutVo> list = this.baseMapper.selectBenefitCardOutVoList(wrapper);
        if (list.size() == 0) {
            return null;
        }
        BenefitCardOutVo outVo = list.get(0);
        // 专题名称
        if (StringUtils.hasLength(outVo.getSalesTopicId())) {
            TopicInfo topicInfo = topicInfoMapper.selectById(outVo.getSalesTopicId());
            outVo.setSalesTopicName(topicInfo.getName());
        }
        // 小程序货币名称和icon
        BaicContent baicContent = iBaicContentService.getThisBaicContent();
        outVo.setWxappCurrency(baicContent.getWxappCurrency());
        outVo.setCurrencyIcon(baicContent.getCurrencyIcon());
        return outVo;
    }

    @Override
    public IPage<CardsInfoOutVo> getCardList(String batch2Num, Long pageNo, Long pageSize) {
        LambdaQueryWrapper<CardsInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(CardsInfo::getSecondBantchNum, batch2Num);

        Page<CardsInfo> page = new Page<>(pageNo, pageSize);
        IPage<CardsInfo> cardsInfoIPage = this.getBaseMapper().selectPage(page, wrapper);

        LambdaQueryWrapper<CardsBatch2> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.like(CardsBatch2::getSecondBantchNum, batch2Num);
        CardsBatch2 batch2 = batch2Mapper.selectOne(wrapper1);

        IPage<CardsInfoOutVo> convert = cardsInfoIPage.convert(CardsInfo -> {
            CardsInfoOutVo form = new CardsInfoOutVo();
            BeanUtils.copyProperties(CardsInfo, form);
            form.setFaceValue(batch2.getFaceValue());
            form.setCompanyName(getCustomerName(batch2.getCustomerId()));
            form.setIsLimitedDate(batch2.getIsLimitedDate());
            form.setStartTime(batch2.getStartTime());
            form.setEndTime(batch2.getEndTime());
            // 是否限制有效期
            if (batch2.getIsLimitedDate() != null && batch2.getIsLimitedDate() == 1) {
                form.setYxq(batch2.getStartTime() + "~" + batch2.getEndTime());
            } else {
                form.setYxq("不限制");
            }
            return form;
        });

        return convert;
    }

    @Override
    public List<BenefitCardOutVo> getFlimBenefitCard() {
        QueryWrapper<BenefitCardOutVo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", TokenService.getUserBytoken().getId());
        wrapper.eq("a.card_type", "DYQ");
        List<BenefitCardOutVo> list = this.baseMapper.selectBenefitCardOutVoList(wrapper);
        if (list.size() > 0) {
            BaicContent baicContent = iBaicContentService.getThisBaicContent();
            list.forEach(a -> {
                a.setWxappCurrency(baicContent.getWxappCurrency());
                a.setCurrencyIcon(baicContent.getCurrencyIcon());
            });
            return list;
        }

        return null;
    }

    @Override
    public IPage<Batch1CardListOutVo> getBatch1CardList(String firstBatchNum, Integer isActivated, Long pageNo,
                                                        Long pageSize) {

        LambdaQueryWrapper<CardsInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CardsInfo::getFirstBatchNum, firstBatchNum);
        wrapper.eq(isActivated != null, CardsInfo::getIsActivated, isActivated);

        Page<CardsInfo> page = new Page<>(pageNo, pageSize);
        IPage<CardsInfo> cardsInfoIPage = this.getBaseMapper().selectPage(page, wrapper);

        IPage<Batch1CardListOutVo> convert = cardsInfoIPage.convert(CardsInfo -> {
            Batch1CardListOutVo form = new Batch1CardListOutVo();
            BeanUtils.copyProperties(CardsInfo, form);
            return form;
        });

        return convert;
    }

    @Override
    public CardUsageOutVo getCardUsage(String batch2Num, Integer distributorId) {
        CardUsageOutVo outVo = new CardUsageOutVo();
        LambdaQueryWrapper<CardsInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CardsInfo::getSecondBantchNum, batch2Num);
        List<CardsInfo> cardsInfos = this.baseMapper.selectList(wrapper);
        int size = cardsInfos.size();
        if (cardsInfos.size() == 0) {
            return outVo;
        }

        // 总激活数
        outVo.setTotalNum(String.valueOf(cardsInfos.size()));
        BigDecimal totalNum = BigDecimal.valueOf(cardsInfos.size());

        // 已使用
        cardsInfos = cardsInfos.stream().filter(a -> StringUtils.hasLength(a.getUserId())).collect(Collectors.toList());
        outVo.setUsedNum(String.valueOf(cardsInfos.size()));
        BigDecimal usedNum = BigDecimal.valueOf(cardsInfos.size());

        CardsBatch2 cardsBatch2 =
                batch2Mapper.selectOne(new LambdaQueryWrapper<CardsBatch2>().eq(CardsBatch2::getSecondBantchNum,
                        batch2Num));
        if (cardsBatch2 == null) {
            return outVo;
        }

        // 总面值
        BigDecimal faceValue = new BigDecimal(cardsBatch2.getFaceValue());
        outVo.setTotalFaceNum(String.valueOf(faceValue.multiply(totalNum)));
        // 未使用面额（元）
        outVo.setUnUsedFaceNum(String.valueOf(totalNum.subtract(usedNum).multiply(faceValue)));

        BigDecimal salePrice = new BigDecimal(cardsBatch2.getSalePrice());
        // 卡券总售价（元）
        outVo.setTotalSale(String.valueOf(totalNum.multiply(salePrice)));

        // 小程序内该批次总收入：激活张数*售价
        outVo.setTotalIncome(String.valueOf(usedNum.multiply(salePrice)));

        // 毛利
        //1. 获取已使用的卡
        List<Integer> cardIdList = cardsInfos.stream().map(CardsInfo::getId).collect(Collectors.toList());
        BigDecimal result = BigDecimal.ZERO;
        BigDecimal xhjscb = BigDecimal.ZERO;
        List<OrderCard> list = iOrderCardService.list();
        for (Integer usedCardId : cardIdList) {
            List<OrderCard> orderCardList = list.stream().filter(orderCard -> Objects.equals(orderCard.getCardId(),
                    usedCardId)).collect(Collectors.toList());
            // Assert.isTrue(!orderCardList.isEmpty(), "数据未埋点！！！");
            if (orderCardList.isEmpty()) {
                continue;
            }
            // 循环得到每个订单积分卡的实际售价
            for (OrderCard orderCard : orderCardList) {

                // 获取已使用的积分
                BigDecimal payAmount = orderCard.getPayAmount();
                BuyerOrder buyerOrder = buyerOrderMapper.selectById(orderCard.getOrderId());
                Assert.notNull(buyerOrder, "订单不存在！！");

                // 获取商品售价
                BigDecimal totalOriginalPrice = buyerOrder.getTotalOriginalPrice();
                BigDecimal margin = buyerOrder.getMargin();

                // 获取卡的售价
                String salePriceStr = cardsBatch2.getSalePrice();
                // 获取卡面值
                String faceValueStr = cardsBatch2.getFaceValue();
                // 毛利额
                result = divideAndMultiply(salePriceStr, faceValueStr, totalOriginalPrice, margin, payAmount);
                xhjscb = getXhjscb(payAmount, totalOriginalPrice, buyerOrder.getCost());
                result = result.add(result);
                xhjscb = xhjscb.add(xhjscb);
            }
        }
        // 批次毛利额
        outVo.setBatchMl(String.valueOf(result));
        // 总面额
        int totalFaceNum = Integer.parseInt(outVo.getTotalFaceNum());
        int unUsedFaceNum = Integer.parseInt(outVo.getUnUsedFaceNum());
        // 使用面额
        int usedFaceNum = totalFaceNum - unUsedFaceNum;
        BigDecimal bigDecimal = BigDecimal.valueOf(usedFaceNum);
        BigDecimal multiply = faceValue.multiply(totalNum);
        BigDecimal divide = bigDecimal.divide(multiply, 2, RoundingMode.UP);
        BigDecimal multiply1 = divide.multiply(BigDecimal.valueOf(100));
        String useRadio = String.valueOf(multiply1).concat("%");
        // 已使用比例
        outVo.setUseRatio(useRadio);
        // 结算成本
        outVo.setXhjscb(String.valueOf(xhjscb));
        // 现金使用率 = 消耗结算成本 /（ 卡售价 * 批次内卡张数 ）
        BigDecimal decimal = faceValue.multiply(BigDecimal.valueOf(size));
        BigDecimal bigDecimal1 = xhjscb.divide(decimal, 2, RoundingMode.UP).multiply(BigDecimal.valueOf(100));
        outVo.setPriceUseRatio(String.valueOf(bigDecimal1).concat("%"));
        return outVo;
    }

    private BigDecimal getXhjscb(BigDecimal payAmount, BigDecimal totalOriginalPrice, BigDecimal cost) {
        //Assert.notNull(cost, "结算成本不能为空！");
        //Assert.isTrue(cost.equals(BigDecimal.ZERO), "结算成本不能为0！");
        // Assert.notNull(totalOriginalPrice, "商品售价不能为空！！");
        //Assert.isTrue(totalOriginalPrice.equals(BigDecimal.ZERO), "商品售价不能为0");
        // TODO：测试用
        if (cost == null || cost.equals(BigDecimal.ZERO)) {
            cost = BigDecimal.ONE;
        }
        if (totalOriginalPrice == null || totalOriginalPrice.equals(BigDecimal.ZERO)) {
            totalOriginalPrice = BigDecimal.ONE;
        }
        return payAmount.divide(totalOriginalPrice, 2, RoundingMode.UP).multiply(cost);
    }

    private BigDecimal divideAndMultiply(String salePriceStr, String faceValueStr, BigDecimal totalOriginalPrice,
                                         BigDecimal margin, BigDecimal amount) {
        BigDecimal number1 = BigDecimal.valueOf(Double.parseDouble(salePriceStr));
        BigDecimal number2 = BigDecimal.valueOf(Double.parseDouble(faceValueStr));
        Assert.notNull(number2, "面额不能为空！");
        // Assert.notNull(margin, "利润不能为空！！");
        // TODO：测试用
        if (margin == null || Objects.equals(margin, BigDecimal.ZERO)) {
            margin = BigDecimal.valueOf(-100);
        }
        Assert.notNull(totalOriginalPrice, "商品售价不能为空！");
        Assert.isTrue(number1.compareTo(BigDecimal.valueOf(0)) > 0, "卡券售价不能为负数");
        Assert.isTrue(number2.compareTo(BigDecimal.valueOf(0)) > 0, "卡券面额不能为负数");
        // 卡售价/卡面额
        BigDecimal divisionResult = number1.divide(number2, 2, RoundingMode.UP);
        // 未使用面额 × 卡售价/卡面额
        BigDecimal multiply = number2.subtract(amount).multiply(divisionResult);
        // 实际使用积分/商品售价 * 商品利润额
        BigDecimal bigDecimal = amount.divide(totalOriginalPrice, 2, RoundingMode.UP).multiply(margin);
        // 结果
        return multiply.add(bigDecimal);
    }

    @Override
    public List<BenefitCardOutVo> getCanPayCards(Integer goodsId) {
        List<BenefitCardOutVo> outVos = new ArrayList<>();

        QueryWrapper<BatchGoods> wrapper1 = new QueryWrapper<>();
        wrapper1.inSql("second_bantch_num",
                "select second_bantch_num from benefit_cards_info where balance > 0 and is_enable = 0 and user_id = '"
                        + TokenService.getUserBytoken().getId() + "'");
        wrapper1.eq("goods_id", goodsId);
        wrapper1.eq("deleted", 0);
        List<BatchGoods> batchGoods = goodsInfoMapper.getBatchGoods(wrapper1);

        // 获得此商品福利卡批次合集
        if (batchGoods.size() == 0) {
            return outVos;
        }

        String bantch2Nums = "";
        StringBuilder bantch2NumsBuilder = new StringBuilder();
        bantch2NumsBuilder.append(bantch2Nums);
        batchGoods.forEach(a -> {
            if (!StringUtils.hasLength(bantch2NumsBuilder)) {
                bantch2NumsBuilder.append("'").append(a.getSecondBantchNum());
            } else {
                bantch2NumsBuilder.append("','").append(a.getSecondBantchNum());
            }
        });
        bantch2Nums = bantch2NumsBuilder.append("'").toString();

        QueryWrapper<BenefitCardOutVo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", TokenService.getUserBytoken().getId());
        wrapper.inSql("a.second_bantch_num", bantch2Nums);
        wrapper.gt("a.balance", 0);
        wrapper.eq("a.is_enable", 0);
        List<BenefitCardOutVo> list = this.baseMapper.selectBenefitCardOutVoList(wrapper);
        if (list.size() == 0) {
            return outVos;
        }

        BaicContent baicContent = iBaicContentService.getThisBaicContent();
        outVos = BeanUtil.copyToList(list, BenefitCardOutVo.class);
        outVos.forEach(a -> {
            a.setWxappCurrency(baicContent.getWxappCurrency());
            a.setCurrencyIcon(baicContent.getCurrencyIcon());
        });
        return outVos;
    }

    @Override
    public String setFlimBatchAddPrice(SetFlimBatchAddPriceInVo inVo) {
        CardsBatch2 cardsBatch2 = batch2Mapper.selectById(inVo.getId());
        if (cardsBatch2 == null) {
            return "未查询到该批次！";
        }

        if (!cardsBatch2.getCardType().equals("DYQ")) {
            return "该批次非电影券批次，无法设置电影加价！";
        }
        cardsBatch2.setFlimBatchAddPrice(inVo.getFlimBatchAddPrice());
        batch2Mapper.updateById(cardsBatch2);
        return "success";
    }

    @Override
    public IPage<OrderCardOutVo> getCardUseInfo(String cardType, String userId, Long pageNo, Long pageSize) {
        QueryWrapper<OrderCardOutVo> wrapper = new QueryWrapper<>();
        wrapper.eq("c.user_id", userId);
        wrapper.eq("cb2.distributor_id", TokenService.getUserBytoken().getCompanyId());
        wrapper.like(StrUtil.isNotBlank(cardType), "c.card_type", cardType);
        Page<OrderCardOutVo> voPage = new Page<>(pageNo, pageSize);
        IPage<OrderCardOutVo> orderCardOutVos = this.baseMapper.selectDetail(voPage, wrapper);
        for (OrderCardOutVo vo : orderCardOutVos.getRecords()) {
            if (vo.getIsLimitedDate() != null && vo.getIsLimitedDate() == 1) {
                vo.setYxq(vo.getStartTime() + "~" + vo.getEndTime());
            } else {
                vo.setYxq("不限制");
            }
            int i = vo.getBalance().compareTo(BigDecimal.valueOf(Long.parseLong(vo.getFaceValue())));
            if (i < 0) {
                vo.setIsInUse(String.valueOf(1));
            } else {
                vo.setIsInUse(String.valueOf(0));
            }
        }

        return orderCardOutVos;
    }

    @Override
    public CardsDetailOutVo getCardDetail(String cardNo) {
        CardsDetailOutVo cardsDetailOutVo = this.baseMapper.selectByCardNo(cardNo);
        if (cardsDetailOutVo != null) {
            switch (cardsDetailOutVo.getCardType()) {
                //JFK-积分卡 DYQ-电影券  LPK-礼品卡
                case "DYQ":
                    cardsDetailOutVo.setCardType("电影券");
                    break;
                case "LPK":
                    cardsDetailOutVo.setCardType("礼品卡");
                    break;
                case "JFK":
                    cardsDetailOutVo.setCardType("积分卡");
                    break;
                default:
                    break;
            }
            int i = cardsDetailOutVo.getBalance().compareTo(cardsDetailOutVo.getFaceValue());
            if (i < 0) {
                cardsDetailOutVo.setIsUsed(1);
            } else {
                cardsDetailOutVo.setIsUsed(0);
            }
        }
        return cardsDetailOutVo;
    }

    /**
     * 获取下游企业名称
     *
     * @param customerId
     */
    private String getCustomerName(Integer customerId) {
        CustomerInfo customerInfo = customerInfoMapper.selectById(customerId);
        if (customerInfo == null) {
            return null;
        }
        return customerInfo.getCustomerName();
    }
}
